package controller

import (
	"fiberTest/internal/model"
	"fiberTest/internal/model/utils"
	validator "fiberTest/internal/validators"
	pkg "fiberTest/pkg/utils"
	"fmt"
	"github.com/gofiber/fiber/v2"
	"log"
	"strings"
	"time"
)

func Hello(c *fiber.Ctx) error {
	// Create cookie
	cookie := new(fiber.Cookie)
	cookie.Name = "john"
	cookie.Value = "doe"
	cookie.Expires = time.Now().Add(24 * time.Hour)

	// Set cookie
	c.Cookie(cookie)

	resp := utils.Resp{
		Code: 200,
		Msg:  "Hello World",
		Data: pkg.GetConfig(),
	}
	return c.JSON(resp)
}

func Exception(c *fiber.Ctx) error {
	panic("got something went wrong")
}

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

// Canshu 参数
func Canshu(c *fiber.Ctx) error {
	// 获取url中的部分路径通过k-v的方式
	params1 := c.Params("name")
	params2 := c.Params("title")
	fmt.Println(params1)
	fmt.Println(params2)
	// 获取url中的int类型的占位符 k-v
	pa, err := c.ParamsInt("id")
	if err != nil {
		fmt.Println("解析id时出现了异常")
	}
	fmt.Println(pa)
	// 获取query参数 k-v
	query1 := c.Query("name")
	query2 := c.Query("age")
	fmt.Println(query1)
	fmt.Println(query2)
	// 获取所有的query
	queries := c.Queries()
	for k, v := range queries {
		fmt.Println("参数为", k, v)
	}
	// 将获取的query放置到struct中
	p := new(Person)
	err = c.QueryParser(p)
	if err != nil {
		return err
	}
	log.Println(p.Name, p.Age)

	resp := utils.Resp{
		Code: 200,
		Msg:  params1 + params2,
		Data: nil,
	}
	return c.JSON(resp)
}

func Jia(c *fiber.Ctx) error {
	return c.SendString(c.Params("+"))
}

func Option(c *fiber.Ctx) error {
	return c.SendString(c.Params("name"))
}

type Student struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Id    int    `json:"id"`
	Class string `json:"class"`
	Power int    `json:"power"`
	Score int    `json:"score"`
}

func Body(c *fiber.Ctx) error {
	// 获取表单参数 k-v
	value := c.FormValue("hot")
	log.Println(value)
	// 解析body中的json
	s := new(Student)
	err := c.BodyParser(s)
	if err != nil {
		log.Println("在解析body时出现了异常", err.Error())
	}
	log.Println("从body中获取的数据为：", s)

	//resp := utils.Resp{
	//	Code: 0,
	//	Msg:  "从body中获取的数据",
	//	Data: s,
	//}
	//return c.JSON(resp)
	raw := c.BodyRaw()
	log.Println(string(raw))
	return c.Send(raw)
}

func ValidateUser(c *fiber.Ctx) error {
	// Create an instance of User
	var user model.User

	// Bind request data to User struct
	if err := c.QueryParser(&user); err != nil {
		return err
	}

	// Validate User struct
	myValidator := validator.NewXValidator()
	validationErrors := myValidator.Validate(user)
	if len(validationErrors) > 0 {
		errMsgs := make([]string, 0)

		for _, err := range validationErrors {
			errMsgs = append(errMsgs, fmt.Sprintf(
				"[%s]: '%v' | 需要实现 '%s'",
				err.FailedField,
				err.Value,
				err.Tag,
			))
		}

		return &fiber.Error{
			Code:    fiber.ErrBadRequest.Code,
			Message: strings.Join(errMsgs, " and "),
		}
	}

	// Logic, validated with success
	return c.SendString("Hello, World!")
}

// 一个能够被全局异常处理器获取的错误

// 自定义错误类型
type customError struct {
	code    int
	message string
}

// 实现 error 接口
func (e customError) Error() string {
	return e.message
}

// Error 查找用法 ctrl+alt+f7
func Error(ctx *fiber.Ctx) error {
	c := customError{
		code:    fiber.StatusBadRequest,
		message: "错误参数",
	}
	return c
}

func Upload(c *fiber.Ctx) error {
	// 通过document读取文件, 文件上传头必须是multipart/form-data格式
	file, err := c.FormFile("document")
	if err != nil {
		customError := customError{
			code:    fiber.StatusBadRequest,
			message: "上传文件时出现异常",
		}
		return customError
	}
	// 将文件保存到指定目录
	// 拼接路径
	path := fmt.Sprintf("./file-lib/%s", file.Filename)
	return c.SaveFile(file, path)
}

func EDouwn(ctx *fiber.Ctx) error {
	return ctx.SendFile("file-does-not-exist")
}

func Exception2(ctx *fiber.Ctx) error {
	//return fiber.ErrServiceUnavailable
	return fiber.NewError(fiber.StatusUnauthorized, "未验证")
}
